
import json
import httpx

from dataclasses import dataclass, fields
from functools import lru_cache
from pathlib import Path
from typing import List
import warnings

from ..utility import getClassFields
from ..utility.constants import SPARK_STORE_PREIFX_URL

class ArchitectureVars:
    x86_64  = 'x86_64'
    aarch64 = 'aarch64'
    loong64 = 'loong64'

    @staticmethod
    def store(arch) -> "str | None":
        if arch == ArchitectureVars.x86_64:
            return "store"
        elif arch == ArchitectureVars.aarch64:
            return "aarch64-store"
        elif arch == ArchitectureVars.loong64:
            return "loong64-store"
        return None

@dataclass
class PackageVars:
    Package      :str = "包名"
    Version      :str = "版本"
    Architecture :str = "架构"
    Size         :str = "大小"
    Filename     :str = "文件名"

@dataclass(init=False)
class AppVars:
    Name             :str = '名称'
    Version          :str = '版本'
    Filename         :str = '文件'
    Torrent_address  :str = '种子'
    Pkgname          :str = '包名'
    Author           :str = '作者'
    Contributor      :str = '贡献者'
    Website          :str = '主页'
    Update           :str = '更新'
    Size             :str = '大小'
    More             :str = '详情'
    Tags             :str = '标签'
    # img_urls         :str = '图片'
    # icons            :str = '图标'

    def __init__(self, **kwargs):
        '''解决 dataclass 自动初始化时候字段名不匹配
        1. 遍历所有字段名存放在 names 中
        2. 遍历 kwargs, 如果 key 在 names 中，则赋值给对应字段
        '''
        names = set([f.name for f in fields(self)])
        for k, v in kwargs.items():
            if k in names:
                setattr(self, k, v)

@lru_cache(maxsize=None)
def requestPackages() -> str | None:
    '''请求 Packages'''
    url = SPARK_STORE_PREIFX_URL + 'store/Packages'
    resp = httpx.get(url, follow_redirects=True)

    if resp.status_code != 200:
        return None
    
    return resp.content.decode(encoding='utf-8', errors='ignore')

# @lru_cache(maxsize=None)
def requestPackage(package: PackageVars) -> AppVars | None:
    ''''''
    url = 'https://mirrors.sdu.edu.cn/spark-store/store/' + (Path(package.Filename).parent / 'app.json').as_posix()
    resp = httpx.get(url, follow_redirects=True)

    if resp.status_code != 200:
        return None
    
    return AppVars(**json.loads(resp.content.decode(encoding='utf-8', errors='ignore')))

def loads(package : str) -> PackageVars:
    ''''''
    fields = getClassFields(PackageVars).keys()

    package = package.strip()
    lines = package.split('\n')

    keymap = {}
    for line in lines:
        for field in fields:
            if line.startswith(field):
                keymap[field] = line.split(':')[1].strip()
                break

    return PackageVars(**dict(keymap))

@lru_cache(maxsize=None)
def loadPackages() -> List[PackageVars]:
    '''加载所有包'''
    packages = []
    content = requestPackages()
    if content is None:
        return []
    for packageinfo in content.split('\n\n'):
        if 'Package' not in packageinfo.strip():
            continue
        packages.append(loads(packageinfo))

    return packages

@lru_cache(maxsize=None)
def request_applist(categoriy: str) -> AppVars | None:
    '''请求 applist.json'''
    url = SPARK_STORE_PREIFX_URL + f'store/{categoriy}/applist.json'
    resp = httpx.get(url, follow_redirects=True)
    
    if resp.status_code != 200:
        return None
    
    return resp.content.decode(encoding='utf-8', errors='ignore')

def toApp(obj: dict) -> AppVars:
    '''可用于当数据结构不符合 AppVars 时转换(手动转换，临时弃用)'''
    warnings.warn('已弃用，已在 AppVars 中进行了参数初始化处理')
    app = {
        'Name': obj['Name'],
        'Version': obj['Version'],
        'Pkgname': obj['Pkgname'],
        'Update': obj['Update'],
        'Size': obj['Size'],
    }
    return AppVars(**app)

@lru_cache(maxsize=None)
def loadApps(categoriy: str) -> List[AppVars]:
    apps = []
    content = request_applist(categoriy)
    if content is None:
        return []
    for appinfo in json.loads(content):
        apps.append(toApp(appinfo))
    return apps

if __name__ == "__main__":
    
    from time import monotonic
    start = monotonic()
    content = requestPackages()
    end = monotonic()
    print(f'time: {end - start}ms')

    start = monotonic()
    content = requestPackages()
    end = monotonic()
    print(f'time: {end - start}ms')

    fields = getClassFields(PackageVars)
    print(fields)

    print(f'Package Count: {len(loadPackages())}')
